#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/exceptions.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <iostream>
#include "pam_srp.hpp"

extern "C" {
#include "srp.h"
}


namespace pam_srp
{
    
    void SRPSettings::parse_file( const std::string & file_name, const std::string & cfg_name )
    {
        using boost::property_tree::ptree;
        using boost::property_tree::ptree_bad_path;
        using boost::property_tree::ptree_bad_data;
    
        ptree pt;

        std::string skey("server");
        std::string pkey("port");
        std::string kkey("public_key_file");
        std::string hkey("hash_algorithm");
        std::string nkey("prime_size");
        std::string ckey("credential_cache");
        std::string ikey("max_cache_entries");
        std::string section_name("");

        if (cfg_name != "")
        {
            skey = cfg_name + ".server";
            pkey = cfg_name + ".port";
            kkey = cfg_name + ".public_key_file";
            hkey = cfg_name + ".hash_algorithm";
            nkey = cfg_name + ".prime_size";
            ckey = cfg_name + ".credential_cache";
            ikey = cfg_name + ".max_cache_entries";
            section_name = std::string("in [") + cfg_name + "]";
        }

        try
        {
            read_ini(file_name, pt);
        }
        catch( std::exception & e )
        {
            throw SRPError(std::string("Failed to load SRP settings file ") +
                           std::string(e.what()));
        }

        try
        {
            server = pt.get<std::string>( skey );
        }
        catch( ptree_bad_path )
        {
            throw SRPError( std::string("Missing required server definition ") +
                            section_name);
        
        }

        try
        {
            port = pt.get<int>( pkey );
        }
        catch( ptree_bad_path )
        {
            throw SRPError( std::string("Missing required port definition ") +
                            section_name);
        
        }
        catch( ptree_bad_data )
        {
            throw SRPError( std::string("Invalid port definition ") +
                            section_name);
        
        }

        try
        {
            public_key_file = pt.get<std::string>( kkey );
        }
        catch( ptree_bad_path )
        {
            throw SRPError( std::string("Missing required public_key_file definition ") +
                            section_name);
        
        }
        
        std::string ha = pt.get(hkey, "SHA1");
        int         ng = pt.get(nkey, 2048);

        if      (ha == "SHA1")   hash_alg = SRP_SHA1;
        else if (ha == "SHA224") hash_alg = SRP_SHA224;
        else if (ha == "SHA256") hash_alg = SRP_SHA256;
        else if (ha == "SHA384") hash_alg = SRP_SHA384;
        else if (ha == "SHA512") hash_alg = SRP_SHA512;
        else
        {
            throw SRPError( std::string("Invalid hash_algorithm definition ") +
                            section_name );
        }

        if      (ng == 1024) ng_type = SRP_NG_1024;
        else if (ng == 2048) ng_type = SRP_NG_2048;
        else if (ng == 4096) ng_type = SRP_NG_4096;
        else if (ng == 8192) ng_type = SRP_NG_8192;
        else
        {
            throw SRPError( std::string("Invalid prime_size definition ") +
                                    section_name );
        }

        

        cred_cache_file  = pt.get(ckey, "");
        max_cached_creds = pt.get(ikey, 10);
    }

}// end namespace pam_srp

